package wangjg.commons.bean;

import java.io.IOException;
import java.io.InputStream;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.apache.commons.beanutils.BeanUtils;
import org.dom4j.Document;
import org.dom4j.Element;
import org.dom4j.Node;
import org.dom4j.io.SAXReader;

/**
 * 
 * @author wangjg
 *
 */
public class XmlBeanParser {
	
	public static Map<String,Object> getContext(String xmlPath){
		Map<String,Object> context = new HashMap<String,Object>();
		InputStream is = XmlBeanParser.class.getResourceAsStream(xmlPath);
		try {
			SAXReader xreader = new SAXReader();
			Document document = xreader.read(is);
			Element root = document.getRootElement();
			List<Element> list = root.selectNodes("/beans/bean");
			for(Element e : list){
				String id = e.attributeValue("id");
				Object bean = loadBean(e, context);
				context.put(id, bean);
			}
		} catch (Exception e) {
			throw new RuntimeException(e);
		}finally{
			try {
				is.close();
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
		return context;
	}
	
	public static Object loadBean(Element beanElement, Map<String,Object> context){
		Object bean = null;
		String className = beanElement.attributeValue("class");
		try {
			bean  = Class.forName(className).newInstance();
			setProperties(bean, beanElement, context);
		} catch (Exception e) {
			e.printStackTrace();
		}
		return bean;
	}

	public static void setProperties(Object bean, Element beanElement, Map<String,Object> context){
		set(bean, beanElement, "property", context);
	}
	
	public static void setProperties(Object bean, Element beanElement){
		set(bean, beanElement, "property", null);
	}
	
	protected static void set(Object bean, Element beanElement, String propertyTagName, Map<String,Object> context){
        List<Element> params = beanElement.elements(propertyTagName);
        for(Element param: params){
			String name = param.attributeValue("name");
			Object value = param.attributeValue("value");
			String ref = param.attributeValue("ref");
        	if(value==null){
        		String str = param.getTextTrim();
        		if(str!=null&&str.length()>0){
        			value = str;
        		}
        	}
        	if(value==null && ref!=null && context!=null && context.get(ref)!=null){
        		value = context.get(ref);
        	}
        	if(value==null){
        		Element ve = param.element("bean");
        		if(ve!=null){
            		value = loadBean(ve, context);	
        		}
        	}
        	try {
				BeanUtils.setProperty(bean, name, value);
			} catch (Exception e) {
				e.printStackTrace();
			}
        }
	}
	
	public static void copyChildren(Document source, Document target) {
		Element targetRoot=target.getRootElement();
//		Element sourceRoot=source.getRootElement();
		List list=source.getRootElement().selectNodes("./*");
		for(Object o: list){
			Node node = (Node)o;
//			sourceRoot.remove(node);
			targetRoot.add(node);
		}
	}
}
